﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

namespace Sinc.ERP.Application;

/// <summary>
/// 客户信息服务 🧩
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class CustomerService : CustomBaseService, IDynamicApiController
{
    private readonly SqlSugarRepository<SysOrg> _customerRep;
    private readonly ISqlSugarClient _sqlSugarClient;

    public CustomerService(SqlSugarRepository<SysOrg> customerRep, ISqlSugarClient sqlSugarClient)
    {
        _customerRep = customerRep;
        _sqlSugarClient = sqlSugarClient;
    }

    /// <summary>
    /// 查询所有客户信息 🔍
    /// </summary>
    /// <returns></returns>
    [DisplayName("查询所有客户信息")]
    [ApiDescriptionSettings(Name = "dropdownData"), HttpPost]
    public async Task<IList<CustomerOutput>> DropdownData()
    {
        var modelList = await this._customerRep.AsQueryable().Where(x => x.Pid == Sinc.ERP.Core.SeedData.SysOrgSeedData.CustomerOrgId).Select<CustomerOutput>().ToListAsync();
        var defaultOrg = await this._customerRep.GetByIdAsync(Sinc.ERP.Core.SeedData.SysOrgSeedData.DefaultOrgId);
        modelList.Insert(0, defaultOrg.Adapt<CustomerOutput>());
        return modelList;
    }

    /// <summary>
    /// 分页查询客户信息 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("分页查询客户信息")]
    [ApiDescriptionSettings(Name = "Page"), HttpPost]
    public async Task<SqlSugarPagedList<CustomerOutput>> Page(PageCustomerInput input)
    {
        input.Keyword = input.Keyword?.Trim();
        var query = _customerRep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword) || u.Code.Contains(input.Keyword) || u.Remark.Contains(input.Keyword))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .Where(u => u.Pid == Sinc.ERP.Core.SeedData.SysOrgSeedData.CustomerOrgId && u.Status == StatusEnum.Enable)
            .Select<CustomerOutput>();
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 获取客户信息详情 ℹ️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取客户信息详情")]
    [ApiDescriptionSettings(Name = "Detail"), HttpGet]
    public async Task<CustomerOutput> Detail([FromQuery] QueryByIdCustomerInput input)
    {
        var model = await _customerRep.GetFirstAsync(u => u.Id == input.Id);
        return model.Adapt<CustomerOutput>();
    }

    /// <summary>
    /// 增加客户信息 ➕
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("增加客户信息")]
    [ApiDescriptionSettings(Name = "Add"), HttpPost, UnitOfWork]
    public async Task<long> Add(AddCustomerInput input)
    {
        if (await _customerRep.IsAnyAsync(u => u.Name != null && u.Name == input.Name))
            throw Oops.Oh("联系人姓名已存在");

        var model = new SysOrg
        {
            Id = YitIdHelper.NextId(),
            Pid = Sinc.ERP.Core.SeedData.SysOrgSeedData.CustomerOrgId,
            Name = input.Name,
            Code = input.Code,
            Remark = input.Remark,
            Type = "201",
            Level = 100,
            OrderNo = 100,
            Status = StatusEnum.Enable,
            TenantId = SqlSugarConst.DefaultTenantId,
        };
        var user = new SysUser
        {
            Id = YitIdHelper.NextId(),
            OrgId = model.Id,
            Account = input.LoginName.Trim(),
            RealName = input.Name,
            Password = CryptogramUtil.Encrypt(input.Password),
            Sex = GenderEnum.Male,
            Birthday = DateTime.Now,
            Phone = input.Code,
            CardType = CardTypeEnum.IdCard,
            CultureLevel = CultureLevelEnum.Level0,
            OrderNo = 100,
            Status = StatusEnum.Enable,
            AccountType = AccountTypeEnum.Member,
            PosId = 1300000000102,
            TenantId = SqlSugarConst.DefaultTenantId,
            Remark = input.Remark,
            Address = input.Remark,
        };
        var userOrg = new SysUserRole
        {
            Id = YitIdHelper.NextId(),
            UserId = user.Id,
            RoleId = Sinc.ERP.Core.SeedData.SysRoleSeedData.CustomerRoleId,
        };

        var isExits = await _sqlSugarClient.Queryable<SysUser>().AnyAsync(x => x.Account == user.Account);
        if (isExits)
            throw Oops.Oh($"{input.LoginName} 已经存在");

        await _customerRep.AsInsertable(model).ExecuteCommandAsync();
        await _sqlSugarClient.Insertable(user).ExecuteCommandAsync();
        await _sqlSugarClient.Insertable(userOrg).ExecuteCommandAsync();

        return model.Id;
    }

    /// <summary>
    /// 更新客户信息 ✏️
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新客户信息")]
    [ApiDescriptionSettings(Name = "Update"), HttpPost]
    public async Task Update(UpdateCustomerInput input)
    {
        if (await _customerRep.IsAnyAsync(u => u.Id != input.Id && u.Name != null && u.Name == input.Name))
            throw Oops.Oh("联系人姓名已存在");

        var model = await _customerRep.GetByIdAsync(input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        model.Name = input.Name;
        model.Code = input.Code;
        model.Remark = input.Remark;
        await _customerRep.AsUpdateable(model).ExecuteCommandAsync();
    }

    /// <summary>
    /// 删除客户信息 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除客户信息")]
    [ApiDescriptionSettings(Name = "Delete"), HttpPost, UnitOfWork]
    public async Task Delete(DeleteCustomerInput input)
    {
        var model = await _customerRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        model.Status = StatusEnum.Disable;
        await _customerRep.AsUpdateable(model).ExecuteCommandAsync();
        await _sqlSugarClient.Updateable<SysUser>().SetColumns(x => x.Status == StatusEnum.Disable).Where(x => x.OrgId == model.Id).ExecuteCommandAsync();

        //await _customerRep.FakeDeleteAsync(entity);   //假删除
        //await _customerRep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 批量删除客户信息 ❌
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("批量删除客户信息")]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    public async Task<int> BatchDelete([Required(ErrorMessage = "主键列表不能为空")] List<DeleteCustomerInput> input)
    {
        //var exp = Expressionable.Create<Customer>();
        //foreach (var row in input) exp = exp.Or(it => it.Id == row.Id);
        //var list = await _customerRep.AsQueryable().Where(exp.ToExpression()).ToListAsync();

        //return await _customerRep.FakeDeleteAsync(list);   //假删除
        //return await _customerRep.DeleteAsync(list);   //真删除
        return 0;
    }

    /// <summary>
    /// 导出客户信息记录 🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("导出客户信息记录")]
    [ApiDescriptionSettings(Name = "Export"), HttpPost, NonUnify]
    public async Task<IActionResult> Export(PageCustomerInput input)
    {
        var list = (await Page(input)).Items?.Adapt<List<ExportCustomerOutput>>() ?? new();
        if (input.SelectKeyList?.Count > 0) list = list.Where(x => input.SelectKeyList.Contains(x.Id)).ToList();
        return ExcelHelper.ExportTemplate(list, "客户信息导出记录");
    }

    /// <summary>
    /// 下载客户信息数据导入模板 ⬇️
    /// </summary>
    /// <returns></returns>
    [DisplayName("下载客户信息数据导入模板")]
    [ApiDescriptionSettings(Name = "Import"), HttpGet, NonUnify]
    public IActionResult DownloadTemplate()
    {
        return ExcelHelper.ExportTemplate(new List<ExportCustomerOutput>(), "客户信息导入模板");
    }

    /// <summary>
    /// 导入客户信息记录 💾
    /// </summary>
    /// <returns></returns>
    [DisplayName("导入客户信息记录")]
    [ApiDescriptionSettings(Name = "Import"), HttpPost, NonUnify, UnitOfWork]
    public IActionResult ImportData([Required] IFormFile file)
    {
        lock (this)
        {
            var stream = ExcelHelper.ImportData<ImportCustomerInput, Customer>(file, (list, markerErrorAction) =>
            {
                _sqlSugarClient.Utilities.PageEach(list, 2048, pageItems =>
                {
                    // 校验并过滤必填基本类型为null的字段
                    var rows = pageItems.Adapt<List<Customer>>();

                    var storageable = _customerRep.Context.Storageable(rows)
                        .SplitError(it => it.Item.Name?.Length > 50, "联系人姓名长度不能超过50个字符")
                        .SplitError(it => it.Item.Telphone?.Length > 50, "联系电话长度不能超过50个字符")
                        .SplitError(it => it.Item.Address?.Length > 500, "详细地址长度不能超过500个字符")
                        .WhereColumns(it => new { it.Name }).SplitError(it => it.Any(), "联系人姓名已存在")
                        .SplitInsert(_ => true)
                        .ToStorage();

                    if (rows.Any())
                    {
                        storageable.BulkCopy();
                        storageable.BulkUpdate();
                    }
                    // 标记错误信息
                    markerErrorAction.Invoke(storageable, pageItems, rows);
                });
            });

            return stream;
        }
    }
}
